package com.alit.face.koala.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.tomcat.util.codec.binary.Base64;
import org.json.JSONArray;
import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alit.face.koala.bean.http.KoalaRequestData;
import com.alit.face.koala.entity.KoalaCemara;
import com.alit.face.koala.entity.KoalaEmpLoyeeEntity;
import com.alit.face.koala.entity.KoalaHost;
import com.alit.face.koala.entity.UploadFileEntity;
import com.alit.face.koala.projectvariable.PVK;
import com.alit.face.koala.repository.KoalaEmployeeRepository;
import com.alit.face.koala.repository.KoalaHostRepository;
import com.alit.face.koala.service.face.baidu.BaiduFaceService;
import com.alit.face.koala.service.subject.BaiduFaceDetecteService;
import com.alit.face.koala.service.upload.UploadService;
import com.alit.face.koala.util.JsonUtil;
import com.alit.face.koala.util.NameUtil;
import com.alit.face.koala.vo.GreetingVO;
import com.litong.utils.http.commonshttpclient.HttpConstant;
import com.litong.utils.projectvariable.PVU;

import lombok.extern.slf4j.Slf4j;

/**
 * @author litong
 * @date 2019年4月26日_下午2:07:45
 * @version 1.0
 */
@Service
@Slf4j
public class CallBackService {

  // screen_token+员工Id和上一次人脸识别成功的时间戳,秒
  private Map<String, Long> lastRecognitionTime = new HashMap<>();
  @Autowired
  private KoalaHostService koalaHostService;
  @Autowired
  private KoalaHostRepository koalaHostRepository;
  @Autowired
  private KoalaCemaraService kcs;
  @Autowired
  private BaiduFaceService baiduFaceService;
  @Autowired
  private KoalaEmployeeRepository koalaEmployeeRepository;
  @Autowired
  private KoalaEmployeeSerivce koalaEmployeeService;
  @Autowired
  private FaceKoalaService faceKoalaService;
  @Autowired
  private UploadService uploadService;
  @Autowired
  private BaiduFaceDetecteService baiduFaceDetecteService;
  @Autowired
  private KoalaStrangerSerive koalaStrangerSerive;
  @Autowired
  private KoalaMqService koalaMqService;
  @Autowired
  private KoalaHistoryCallbackService koalaHistoryCallbackServcie;

  /**
   * 处理koala的请求 先尝试使用默认的用户名和密码登陆 默认用户名 litngjava@qq.com 默认密码 123456 如果登陆失败则抛出提示
   * 1.如果图片大于2M,将图片进行缩放,图片缩放后上传到fdfs,
   * 
   * @param koalaRequestData
   */
  public void process(KoalaRequestData koalaRequestData, String ip) {
    // 从数据库中查询出通道
    KoalaCemara koalaCemara = kcs.findTopic(koalaRequestData.getScreenToken());

    // 检测是否配了用户名和密码,如果没有配置使用默认的用户名和密码是佛可以验证通过
    KoalaHost koalaHost = koalaHostService.findByIP(ip);
    String message = null;
    if (StringUtils.isEmpty(koalaHost)) { // 没有IP,保存Ip,让虚拟人像播放一段文字
      koalaHost = new KoalaHost();
      koalaHost.setIp(ip);
      koalaHost.setMasterIp(ip);
      koalaHostRepository.save(koalaHost);
      message = "系统异常,本系统中没有" + ip + "用户名和密码";
    }
    // 验证有没有用户名和密码
    String koalaUrl = "http://" + koalaHost.getMasterIp();
    String username = koalaHost.getUsername();
    String password = koalaHost.getPassword();
    // 当没有配置用户名和密码是是否使用独立的用户名和密码进行尝试
    boolean useDefault = false;
    if (StringUtils.isEmpty(username)) {
      username = PVU.getValue(PVK.koalaDefaultUsername);
      useDefault = true;
    }
    if (StringUtils.isEmpty(password)) {
      password = PVU.getValue(PVK.koalaDefaultPassword);
      useDefault = true;
    }

    if (useDefault == true) { // 使用默认的用户和密码尝试登陆,如果登陆失败,发送错误消息,并且使用缓存
      int authLogin = faceKoalaService.authLogin(koalaUrl, username, password, true);
      if (authLogin != 0) {
        koalaMqService.sendMessage(koalaCemara, GreetingVO.buildStranger(message));
        return;
      }
    }

    byte[] bytes = Base64.decodeBase64(koalaRequestData.getPhoto());
    UploadFileEntity uploadFileEntity = uploadService.uploadImageFace(bytes, "jpeg");

    String greeting = PVU.getValue(PVK.projectGreeting);
    boolean isGreeting = PVU.getValue(PVK.koalaStrangerSayHello).equals("true");

    int sbujectID = koalaRequestData.getSubjectId();
    String userId = sbujectID + "";
    // 实际测试中发现 -1 是陌生人
    String name = null;
    int gender = 0;
    String idCard = null; // 身份证号
    if (StringUtils.isEmpty(sbujectID) || sbujectID == 0 || sbujectID == -1) { // sbujectID为空说明是陌生人
      log.info("识别到陌生人:isGreeting={}", isGreeting);
      if (isGreeting) {
        koalaStrangerSerive.index(koalaRequestData, ip, koalaCemara, uploadFileEntity);
      }
      return;
    }
    if (name == null) { // 识别到的不是陌生人,获取用户名
      Map<String, String> responseMap = faceKoalaService.getStaffNameByID(koalaUrl, username, password, sbujectID);
      int httpStatus = Integer.parseInt(responseMap.get(HttpConstant.stauts));
      if (httpStatus != 200) {
        koalaMqService.sendMessage(koalaCemara, GreetingVO.buildStranger("获取员工信息失败,检查和koala的主机的通讯是否正常"));
      }
      JSONObject parseObject = JSON.parseObject(responseMap.get(HttpConstant.value));
      int code = parseObject.getIntValue("code");
      if (code != 0) {
        koalaMqService.sendMessage(koalaCemara, GreetingVO.buildStranger("获取员工信息失败,检查配置的用户和密码是否正确"));
        log.info("获取员工信息是失败,错误信息:" + parseObject.toJSONString());
      }
      JSONObject subject = parseObject.getJSONObject("data");
      //log.info("获取到用户:" + subject);
      name = subject.getString("name");
      gender = subject.getIntValue("gender");
      idCard = subject.getString("remark");
      //log.info("识别到用户,{},{}", name, idCard);
    }

    // 判断识别相隔时间,如果在40s,则不打招呼
    String screen_token = koalaRequestData.getScreenToken();
    Long lastTime = lastRecognitionTime.get(screen_token + userId);
    log.info(
        "上次摄像头:" + screen_token + "员工:" + userId + "的识别时间是:" + lastTime + "这次是:" + koalaRequestData.getTimestamp());
    if (isSend(koalaRequestData.getTimestamp(), lastTime)) {// lastTime

      String lastname = NameUtil.getLastname(name);
      if (gender == 1) {
        if (isStrangerName(name)) {
          message = PVU.getValue(PVK.koalaStrangerSayString);
        } else {
          message = greeting.replace("${lastname}", lastname).replace("${name}", name).replace("${gender}", "先生");
        }
        koalaMqService.sendMessage(koalaCemara, GreetingVO.buildFamiliar(message, name, idCard));
      } else {
        if (isStrangerName(name)) {
          message = PVU.getValue(PVK.koalaStrangerSayString);
        } else {
          message = greeting.replace("${lastname}", lastname).replace("${name}", name).replace("${gender}", "女士");
        }
        koalaMqService.sendMessage(koalaCemara, GreetingVO.buildFamiliar(message, name, idCard));
      }
      koalaHistoryCallbackServcie.saveHistory(koalaRequestData, ip, name, gender, true);
    } else {
      koalaHistoryCallbackServcie.saveHistory(koalaRequestData, ip, name, gender, false);
      log.info("识别到,在规定的间隔时间内,不到招呼");
    }
    // 更新记录时间
    lastRecognitionTime.put(screen_token + userId, koalaRequestData.getTimestamp());
  }

  private boolean isSend(Long timestamp, Long lastTime) {
    int interval = Integer.parseInt(PVU.getValue(PVK.koalaRecognizeInterval));
    if (lastTime == null || timestamp - lastTime > interval)
      return true;
    return false;
  }

  /**
   * 陌生人打招呼处理逻辑
   * 1.查询人脸库,判断陌生人是否已经存在 
   * 2.如果不存在,将陌生人添加到人脸库
   * 出现问题返回null,调用程序会进行判断
   */
  public KoalaEmpLoyeeEntity saveStranger(UploadFileEntity uploadFile, String koalaUrl, String username,
      String password) {

    if (PVU.getBooleanValue(PVK.enableFaceKoala)) { // 添加陌生用户名到koala
      // 1.将图片上传到koala,获取图片Id
      // 2.将图片和用户添加到face-koal
      JSONObject jsonObject = faceKoalaService.subjectPhoto(koalaUrl, username, password,
          uploadFile.getLocalFilePath());
      int code = jsonObject.getIntValue("code");
      if (code != 0) {// 上传照片失败,返回null
        return null;
      }
      String phototId = jsonObject.getJSONObject("data").getString("id");
      if (PVU.isDev()) {
        log.info("上传用户照片到kola,photo_id," + phototId);
      }
      KoalaEmpLoyeeEntity employee = new KoalaEmpLoyeeEntity();

      employee.setName(getName(System.currentTimeMillis()));
      employee.setDepartment("陌生人组");
      employee.setTitle("陌生人");
      employee.setSubjectType(0);

      List<String> photos = new ArrayList<>();
      photos.add(phototId);
      jsonObject = faceKoalaService.subject(koalaUrl, username, password, employee, photos);
      return employee;
    }

    KoalaEmpLoyeeEntity retval = null;
    // 上传陌生图片到百度
    // 检测人脸获取性别和face_token
    String encodeBase64String = Base64.encodeBase64String(uploadFile.getBytes());
    String image = encodeBase64String;
    org.json.JSONObject detected = baiduFaceDetecteService.detected(uploadFile);

    int errorCode = -1;
    try {
      errorCode = detected.getInt("error_code");
      if (errorCode != 0) {
        log.info("图片检测出现问题:" + detected);
        return null;
      }
    } catch (JSONException e) {
      log.error("获取图片检测检测错误码异常:" + e.getMessage());
      return null;
    }

    org.json.JSONObject result = JsonUtil.getJSONObject(detected, "result");
    JSONArray faseList = JsonUtil.getJSONArray(result, "face_list");
    org.json.JSONObject face = JsonUtil.getJSONObject(faseList, 0);
    String faceToken = JsonUtil.getString(face, "face_token");
    org.json.JSONObject gender = JsonUtil.getJSONObject(face, "gender");
    String type = JsonUtil.getString(gender, "type");
    int genderType = 0;
    if ("male".equals(type))
      genderType = 1;
    genderType = 2;

    // 搜索人脸
    String imageType = "FACE_TOKEN";
    String groupIdList = PVU.getValue(PVK.baiduFaceGroups);
    org.json.JSONObject search = baiduFaceService.search(faceToken, imageType, groupIdList);
    log.info("人脸搜索结果:" + search);
    // 获取error_code;
    errorCode = JsonUtil.getInt(search, "error_code");

    String userId = null;
    String name = null;
    String userInfo = null;
    if (errorCode == 0) {// 搜索到已经存在的用户
      result = JsonUtil.getJSONObject(search, "result");
      // 获取face_token
      faceToken = JsonUtil.getString(result, "face_token");
      JSONArray userList = JsonUtil.getJSONArray(result, "user_list");
      org.json.JSONObject user = JsonUtil.getJSONObject(userList, 0);
      userInfo = JsonUtil.getString(user, "user_info");
      userId = JsonUtil.getString(user, "user_id");
      log.info("从远程库中搜索到人脸,同步到本地库中:" + userId);
      retval = koalaEmployeeService.saveIfNotExists(userId, userInfo);
    } else {// 没有搜索到用户
      log.info("没有搜索到人脸,添加本地库和远程库");
      // 1.将用户添加到人脸库,先保存到本地人脸库,在添加到远程人脸库
      retval = new KoalaEmpLoyeeEntity();
      name = "stranger_" + System.currentTimeMillis();
      retval.setGender(genderType);
      retval.setName(name);
      retval.setDepartment("陌生人组");
      retval.setTitle("陌生人");
      com.alibaba.fastjson.JSONArray jsonArray = new com.alibaba.fastjson.JSONArray();
      jsonArray.add(uploadFile.getMd5());
      retval.setPhotoIds(jsonArray.toJSONString());
      retval = koalaEmployeeRepository.save(retval);
      log.info("添加用户到本地成功:" + retval.getId() + "," + retval.getName());
      image = faceToken;
      imageType = "FACE_TOKEN";
      String groupId = "1";// 陌生人用户组
      userId = retval.getId();
      HashMap<String, String> options = new HashMap<>(1);
      options.put("user_info", JSON.toJSONString(retval));
      org.json.JSONObject add = baiduFaceService.add(image, imageType, groupId, userId, options);
      log.info("添加用户到百度返回:" + add);
    }
    return retval;
  }

  private String getName(Long timestamp) {
    return "stranger_" + timestamp;
  }

  // 如果名字中包含陌生人标识
  private boolean isStrangerName(String name) {
    return name.startsWith("stranger_");
  }
}
